package cn.sys.service.impl;

import cn.sys.dao.StuSecurityQuestionAnswerDao;
import cn.sys.dao.StudentDao;
import cn.sys.entity.SecurityQuestion;
import cn.sys.entity.StuSecurityQuestionAnswer;
import cn.sys.entity.Student;
import cn.sys.service.StudentService;
import cn.sys.util.MybatisUtil;
import cn.sys.util.ResultData;
import cn.sys.util.SecurityQuestionCacheUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.Date;
import java.util.List;

public class StudentServiceImpl implements StudentService {
    /*private SqlSession sqlSession = MybatisUtil.getSQLSession();*/

    /**
     * 处理登录的业务逻辑
     * @param studentName 用户名
     * @param password 密码
     * @return
     */
    @Override
    public ResultData login(String studentName, String password) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StudentDao studentDAO = sqlSession.getMapper(StudentDao.class);
        Student student = studentDAO.findStudentByNameAndPassword(studentName, password);

        //关闭SqlSession连接
        MybatisUtil.closeSqlSession(sqlSession);

        if (student == null){
            return new ResultData(ResultData.LOGIN_FAIL,"登录失败",null);
        }
        return new ResultData(ResultData.LOGIN_SUCCESS,"登录成功",student);
    }

    /**
     * 登录成功，将登录失败次数置为0，并修改登录时间
     * @param loginTime
     * @param stuId
     * @return
     */
    @Override
    public ResultData updateLoginCountAndLoginTime(Date loginTime, int stuId) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        int i = studentDao.updateLoginCountAndLoginTime(loginTime, stuId);
        if(i > 0){
            return ResultData.ok(ResultData.OPERATION_SUCCESS, "修改用户登录时间和失败次数成功");
        }
        return ResultData.fail(ResultData.OPERATION_FAIL,"修改用户登录时间和失败次数失败");
    }

    /**
     * 用户登录失败，将失败次数加1，如果次数累加到5，就冻结账户
     * @param stuName
     * @return
     */
    @Override
    public ResultData addLoginCountByName(String stuName) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);

        // 如果失败次数少于5次，就加一；如果超过5次，就冻结账户
        int i = studentDao.findFailCount(stuName);
        if(i >= 4){
            studentDao.updateStudentLockState(stuName, 1, new Date());
            return ResultData.ok(ResultData.STUDENT_LOCKED_STATE, "账号已被冻结");
        }

        int j = studentDao.addLoginCountByName(stuName);
        if(j>0){
            return ResultData.ok(ResultData.OPERATION_SUCCESS, "您还有"+(4-i)+"次机会");
        }
        return ResultData.ok(ResultData.OPERATION_SUCCESS, "登录失败次数加一操作失败（有可能是用户名不存在）");
    }

    /**
     * 在登录之前，判断输入用户名所在的账号是否冻结，如果冻结则不能登录
     * @param stuName
     * @return
     */
    @Override
    public ResultData checkStudentLockState(String stuName) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Integer i = studentDao.findStudentLockState(stuName);
        if(i == 1){ // 账户被冻结
            return ResultData.fail(ResultData.STUDENT_LOCKED_STATE, "账号已被冻结，不能登录，请联系管理员解冻");
        }
        return ResultData.ok(ResultData.STUDENT_UNLOCK_STATE, "账号状态正常，可以登录");
    }

    /**
     * 用户在登录情况下，修改密码
     * @param stuId
     * @param newPassword
     * @return
     */
    @Override
    public ResultData updatePassword(int stuId, String newPassword) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        int i = studentDao.updatePassword(newPassword, stuId);
        if(i>0){
            return ResultData.ok(ResultData.OPERATION_SUCCESS, "密码修改成功");
        }
        return ResultData.fail(ResultData.OPERATION_FAIL, "密码修改失败，请稍后再试");
    }

    /**
     * 获取所有的密保问题
     * @return
     */
    @Override
    public ResultData findAllSecurityQuestion() {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StuSecurityQuestionAnswerDao answerDao = sqlSession.getMapper(StuSecurityQuestionAnswerDao.class);
        List<SecurityQuestion> securityQuestions = answerDao.findAllSecurityQuestion();
        ResultData resultData = new ResultData(ResultData.OPERATION_SUCCESS, "", securityQuestions);
        return resultData;
    }

    /**
     * 处理用户忘记密码时，输入用户名或电话，显示密保问题的业务
     * @param studentNameOrPhone 用户名或电话
     * @return
     */
    @Override
    public ResultData findQuestion(String studentNameOrPhone) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Student student = studentDao.findStudentByNameOrPhone(studentNameOrPhone);
        // 1. 当输入的数据在数据库中没有找到时
        if(student == null){
            return ResultData.fail(ResultData.OPERATION_FAIL, "用户名或电话不存在，请重新输入");
        }

        // 2. 有数据时，查询密保问题
        StuSecurityQuestionAnswerDao stuSecurityQuestionAnswerDao = sqlSession.getMapper(StuSecurityQuestionAnswerDao.class);
        List<String> questions = stuSecurityQuestionAnswerDao.findQuestionsByStudentNameOrPhone(studentNameOrPhone);
        if(questions.isEmpty()){
            return ResultData.fail(ResultData.OPERATION_FAIL, "您当前还没有设置密保问题");
        }
        ResultData resultData = new ResultData();
        resultData.put("code", ResultData.OPERATION_SUCCESS);
        resultData.put("questions", questions);
        resultData.put("stuId", student.getStuId());
        resultData.put("stuName", student.getStuName());

        return resultData;
    }

    /**
     * 验证用户密保答案是否正确
     * @param sessionId
     * @param stuId  用户id
     * @param question  用户选择的密保问题
     * @param answer    用户输入的密保答案
     * @return
     */
    @Override
    public ResultData checkAnswer(String sessionId, int stuId, String question, String answer) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StuSecurityQuestionAnswerDao stuSecurityQuestionAnswerDao = sqlSession.getMapper(StuSecurityQuestionAnswerDao.class);
        StuSecurityQuestionAnswer questionAnswer = stuSecurityQuestionAnswerDao.findStuSecurityQuestionAnswer(stuId, question, answer);
        // 1. 密保验证失败，直接返回提示信息
        if(questionAnswer == null){
            return ResultData.fail(ResultData.CHECK_SECURITY_QUESTION_FAIL, "密保验证失败，请重新输入");
        }
        // 2. 验证成功，需要存入缓存，修改密码页面要使用
        SecurityQuestionCacheUtil.put(SecurityQuestionCacheUtil.prefix + sessionId, String.valueOf(stuId));
        return ResultData.ok(ResultData.CHECK_SECURITY_QUESTION_SUCCESS, "密保验证成功");
    }

    /**
     * 用户点击忘记密码操作时，修改密码
     * @param sessionId
     * @param newPassword
     * @return
     */
    @Override
    public ResultData forgetUpdatePassword(String sessionId, String newPassword) {
        // 在缓存中看是否有用户信息，如果没有，判断为非法访问
        String value = SecurityQuestionCacheUtil.getValue(SecurityQuestionCacheUtil.prefix + sessionId);
        if (value == null){
            return ResultData.fail(ResultData.OPERATION_FAIL, "请求不合法，请正确输入密保信息再修改密码");
        }
        // 请求合法，修改密码
        Integer stuId = Integer.valueOf(value);
        StudentDao studentDao = MybatisUtil.getSQLSession().getMapper(StudentDao.class);

        int i = studentDao.updatePassword(newPassword, stuId);
        if(i>0){
            return ResultData.ok(ResultData.OPERATION_SUCCESS, "密码修改成功");
        }
        return ResultData.fail(ResultData.OPERATION_FAIL, "密码修改失败，请稍后再试");
    }

    @Override
    public ResultData updateStudentInfo(Student student) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        // 用户名和手机号验重
        Student student1 = studentDao.findOtherStudentByNameOrPhone(student.getPhoneNum(), student.getStuName(), student.getStuId());
        if(student1 != null){
            return ResultData.fail(ResultData.OPERATION_FAIL, "当前用户名或手机号被其他用户占用，请重试");
        }
        // 修改学生信息
        int i = studentDao.updateStudentInfo(student);
        if(i>0){
            return ResultData.ok();
        }
        return ResultData.fail();
    }

    /**
     * 添加密保问题，如果密保问题和学生id已经存在，就将答案修改
     * @param questionAnswer
     * @return
     */
    @Override
    public ResultData addStuSecurityQuestionAnswer(StuSecurityQuestionAnswer questionAnswer) {
        SqlSession sqlSession = MybatisUtil.getSQLSession();
        StuSecurityQuestionAnswerDao questionAnswerDao = sqlSession.getMapper(StuSecurityQuestionAnswerDao.class);
        StuSecurityQuestionAnswer stuSecurityQuestionAnswer = questionAnswerDao.findQuestionAnswerByStuIdAndQuestion(questionAnswer.getStuId(),questionAnswer.getQuestion());
        if(stuSecurityQuestionAnswer != null){
            Date updateTime = new Date();
            int i = questionAnswerDao.updateStuSecurityQuestionAnswer(stuSecurityQuestionAnswer.getId(), questionAnswer.getAnswer(), updateTime);
            if(i>0){
                return ResultData.ok(ResultData.OPERATION_SUCCESS, "您曾添加过该密保问题，答案已为您修改成功！");
            }else {
                return ResultData.fail(ResultData.OPERATION_FAIL, "操作失败，请稍后再试");
            }
        }
        int j = questionAnswerDao.addStuSecurityQuestionAnswer(questionAnswer);
        if(j>0){
            return ResultData.ok(ResultData.OPERATION_SUCCESS, "添加成功！");
        }
        return ResultData.fail(ResultData.OPERATION_FAIL, "操作失败，请稍后再试");
    }
}
